package com.xw.class12;

import java.util.LinkedList;

/**
 * @author XW
 * @data 2024/7/15 9:50
 * @description 判断一棵树是否是完全二叉树 递归解法
 */
public class Code01_IsCBTRecursion {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    public static class Info{
        public boolean isCBT;
        public boolean isFull;
        public int height;

        public Info(boolean isCBT, boolean isFull, int height) {
            this.isCBT = isCBT;
            this.isFull = isFull;
            this.height = height;
        }
    }

    public static boolean isCBT2(Node head){
        return process(head).isCBT;
    }

    public static Info process(Node x){
        if (x == null){
            return new Info(true, true, 0);
        }
        Info leftInfo = process(x.left);
        Info rightInfo = process(x.right);
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;

        boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
        boolean isCBT = false;
        if(leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height){
            isCBT = true;
        }else if(leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height + 1){
            isCBT = true;
        }else if(leftInfo.isCBT && rightInfo.isFull && leftInfo.height == rightInfo.height + 1){
            isCBT = true;
        }else if(leftInfo.isFull && rightInfo.isCBT && leftInfo.height == rightInfo.height ){
            isCBT = true;
        }
        return new Info(isCBT,isFull,height);
    }

    public static boolean isCBT1(Node head){
        if(null == head){
            return true;
        }
        LinkedList<Node> nodes = new LinkedList<>();
        //是否遇到过左右不双全的节点
        boolean leaf = false;
        Node l = null;
        Node r = null;
        nodes.add(head);
        while (!nodes.isEmpty()){
            Node node = nodes.poll();
            l = node.left;
            r = node.right;
            //如果某个节点有右无左 直接返回false 或者前面有节点已经是左右不双全了 那么该节点只能是叶子节点，否则返回false
            if((l == null && r != null) || (leaf && (l != null || r != null ))){
                return false;
            }
            if(l != null){
                nodes.add(l);
            }
            if(r != null){
                nodes.add(r);
            }
            //左右不双全 leaf = true
            if(l== null || r==null) {
                leaf = true;
            }
        }
        return true;

    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isCBT1(head) != isCBT2(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }
}
